package com.pointi.PatternExtractor;

import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.pointi.emoTools.ezDate;

public class ThreadExtractor extends Thread
{
	//____________________________________________________________________________________________________
	// DEF

	ConcurrentLinkedQueue<ThreadExtractor> manager ;
	ConfigurationData conf_data ;
	JDBC jdbc ;

	//____________________________________________________________________________________________________
	// INIT

	public ThreadExtractor(ConcurrentLinkedQueue<ThreadExtractor> manager)
	{
		this.manager = manager ;
	}

	public void start(ConfigurationData conf_data, JDBC jdbc)
	{
		this.manager.add(this) ;
		this.conf_data = conf_data ;
		this.jdbc = jdbc ;
		super.start() ;
	}

	//____________________________________________________________________________________________________
	// RUN

	public void run()
	{
		this.fnExtractPattern() ;
		System.out.println("\n[DONE]") ;
		this.manager.remove(this) ;
	}

	//____________________________________________________________________________________________________
	// Pattern Extrator

	public void fnExtractPattern()
	{
		//____________________________________________________________________________________________________
		
		/** INIT **/
		emoParam param = new emoParam() ; // BASEDATA PARAMETER //
		param.fnInitialize(conf_data.s_param_list, conf_data.s_param_order) ;

		emoPattern range = new emoPattern(param.length()) ;
		emoPattern rangeLimit = new emoPattern(param.length()) ; // MIN, MAX SET //
		emoPattern rangeIndividual = new emoPattern(param.length()) ;
		emoPattern rangeIntersection = new emoPattern(param.length()) ;
		emoPattern rangeAll = new emoPattern(param.length()) ;

		ArrayList<emoPattern> rangeContainer = new ArrayList<emoPattern>() ;
		String date = (conf_data.s_target_date.length() == 0)? ezDate.toString(new Date(), ezDate.YYYYMM) : conf_data.s_target_date ; // TARGET DATE // DEFAULT(TODAY) //

		boolean log = false ;
		jdbc.log = false ;
		
		//int type = JDBC.TYPE_OUT_IN ;
		int type = JDBC.TYPE_IN_OUT ;

		double targetRatio = Double.valueOf(conf_data.s_target_ratio) ;
		int targetCount = jdbc.fnGetTargetCount(targetRatio, date) ;

		this.fnPrepare(targetCount, targetRatio, param, range, rangeLimit, rangeIndividual, rangeIntersection, rangeAll, date, type) ;
		this.fnCalibration(targetCount, param, range, rangeLimit, rangeAll, rangeContainer, date, type, log) ;
		
		
		
		this.fnPrintResult(param, rangeContainer, date) ;
	}
	
	//____________________________________________________________________________________________________
	//

	private void fnPrepare(int targetCount, double targetRatio, emoParam param, emoPattern range, emoPattern rangeLimit, emoPattern rangeIndividual, emoPattern rangeIntersection, emoPattern rangeAll, String date, int type)
	{
		jdbc.fnGetAllDataRange(rangeAll, param, date);
		jdbc.fnGetIntersectionRange(targetRatio, rangeIntersection, param, date) ;
		jdbc.fnGetIndivisualRange(targetCount, rangeIndividual, param, date) ;
		
		rangeAll.fnPrint(param) ;
		rangeAll.fnPrint() ;
		rangeIndividual.fnPrint() ;
		rangeIntersection.fnPrint() ;
		
		if(type == JDBC.TYPE_OUT_IN) {
			for(int i=0; i<param.length(); i++) {
				if(rangeIndividual.min(i) > rangeIntersection.min(i)) { rangeIndividual.min(i, rangeAll.min(i)) ; }
				if(rangeIndividual.max(i) < rangeIntersection.max(i)) { rangeIndividual.max(i, rangeAll.max(i)) ; }
			}
		} else {
			for(int i=0; i<param.length(); i++) {
				if(rangeIndividual.min(i) > rangeIntersection.min(i)) { rangeIndividual.min(i, rangeAll.min(i)) ; }
				if(rangeIndividual.max(i) < rangeIntersection.max(i)) { rangeIndividual.max(i, rangeAll.max(i)) ; }
			}
		}		
		if(type == JDBC.TYPE_OUT_IN) {
			range.fnInitialization(rangeIndividual) ;
			rangeLimit.fnInitialization(rangeIntersection) ;
		} else {
			range.fnInitialization(rangeIntersection) ;
			rangeLimit.fnInitialization(rangeIndividual) ;
		}
		//____________________________________________________________________________________________________
		// LOG

		System.out.println("\n[INPUT PARAMETER COUNT]\n" + param.length()) ;
		System.out.println("\n[INPUT PARAMETER LIST]") ; for(int i=0; i<param.length(); i++) { System.out.print(param.param(i) + "\t") ; } System.out.println("") ;
		System.out.println("\n[INPUT PARAMETER ORDER]") ; for(int i=0; i<param.length(); i++) { System.out.print(param.order(i) + "\t") ; } System.out.println("") ;
		System.out.println("\n[RANGE LIMIT]") ; rangeLimit.fnPrint(param) ; rangeLimit.fnPrint() ;
		System.out.println("\n[INITIAL RANGE]") ; rangeLimit.fnPrint(param) ; range.fnPrint() ;
	}
	
	//____________________________________________________________________________________________________
	// RANGE CALIBRATION

	private void fnCalibration(int targetCount, emoParam param, emoPattern range, emoPattern rangeLimit, emoPattern rangeAll, ArrayList<emoPattern> rangeContainer, String date, int type, boolean log)
	{
		System.out.println("\n[CALIBRATE RANGE]") ;

		emoPattern rangeBuffer = new emoPattern(param.length()) ;
		int listCount = 0 ;
		int paramIndex = 0 ;
		int cnt = 0 ;
		int depth = 0 ;
		double min = 0.0, max = 0.0 ;
		while((paramIndex < param.length() || targetCount > listCount))
		{
			if(paramIndex == param.length()) {
				System.out.println("\n\n[PHASE.2 - EXPAND RANGE-LIMIT]") ;
				paramIndex = 0 ;
				depth = 0 ;
				cnt = 0 ;
				rangeLimit.fnInitialization(rangeAll) ;
			}
			System.out.print(" .") ; cnt++ ; if(cnt >= 80) { System.out.print("\n") ; cnt = 0 ; }
			
			min = jdbc.fnNextRangeMin(param.param(paramIndex), range.min(paramIndex), date, type) ;
			max = jdbc.fnNextRangeMax(param.param(paramIndex), range.max(paramIndex), date, type) ;
			if(min == -1.0) { min = rangeLimit.min(paramIndex) ; }
			if(max == -1.0) { max = rangeLimit.max(paramIndex) ; }
			if(log) System.out.println("[min : max] " + min + " : " + max) ;
			if(type == JDBC.TYPE_OUT_IN) {
				if(min > rangeLimit.min(paramIndex)) { min = rangeLimit.min(paramIndex) ; }
				if(max < rangeLimit.max(paramIndex)) { max = rangeLimit.max(paramIndex) ; }
			} else {
				if(min < rangeLimit.min(paramIndex)) { min = rangeLimit.min(paramIndex) ; }
				if(max > rangeLimit.max(paramIndex)) { max = rangeLimit.max(paramIndex) ; }
			}
			rangeBuffer.fnInitialization(range) ;
			range.min(paramIndex, min) ;
			range.max(paramIndex, max) ;
			listCount = jdbc.fnGetCount(param, range, date) ;
			if(log) System.out.println("[list : target] " + listCount + " : " + targetCount) ;
			boolean isFull = false ;
			boolean isLimit = false ;
			if(type == JDBC.TYPE_OUT_IN && listCount < targetCount) { isFull = true ; }
			if(type == JDBC.TYPE_IN_OUT && listCount > targetCount) { isFull = true ; }
			if(!isFull && min == rangeLimit.min(paramIndex) && max == rangeLimit.max(paramIndex)) { isLimit = true ; }
			if(isFull || isLimit)
			{
				System.out.println(" [Param] " + paramIndex + " [Depth] " + depth) ;
				if (log)
				{
					System.out.println("") ;
					System.out.println("[CHANGE POINT]") ;
					System.out.println("[min : max] " + min + " : " + max) ;
					System.out.println("[list : target] " + listCount + " : " + targetCount) ;
					System.out.println("") ;
				}
				if(isFull) range.fnInitialization(rangeBuffer) ;
				rangeContainer.add(new emoPattern(range)) ;
				paramIndex++ ;
				depth = 0 ;
				cnt = 0 ;
			}
			depth++ ;
		}		
	}
	
	//____________________________________________________________________________________________________

	private void fnPrintResult(emoParam param, ArrayList<emoPattern> rangeContainer, String date)
	{
		System.out.println("\n[CALIBRATED RANGE LIST]") ;
		for(int i=0; i<rangeContainer.size(); i++)
		{
			System.out.println(String.format("\n[RANGE SET(%02d)]", i)) ;
			rangeContainer.get(i).fnPrint(param) ;
			rangeContainer.get(i).fnPrint() ;
		}
		for(int i=0; i<rangeContainer.size(); i++)
		{
			System.out.println(String.format("\n--[RANGE SET(%02d)]", i)) ;
			rangeContainer.get(i).fnPrint(param, date) ;
		}
	}

	//____________________________________________________________________________________________________
	// EOC
}